home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1991: Code Warrior / bincue / Code Warrior.bin / Developer Essentials / DTS Sample Code / System 7.0 Samples / CShell / AppleEvents2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-21  |  23.6 KB  |  891 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:        CShell
  5. ** File:        AppleEvents2.c
  6. ** Written by:  Eric Soldan
  7. **
  8. ** Copyright © 1990-1991 Apple Computer, Inc.
  9. ** All rights reserved.
  10. **
  11. ** This is the custom AppleEvents code.  The required AppleEvents code is in
  12. ** the file AppleEvents.c, which is Keith Rollin's work.
  13. */
  14.  
  15.  
  16.  
  17. /*****************************************************************************/
  18.  
  19.  
  20.  
  21. #include "CShell.h"                /* Get the CShell includes/typedefs, etc.    */
  22. #include "CShellCommon.h"        /* Get the stuff in common with rez.        */
  23. #include "CShell.protos"        /* Get the prototypes for CShell.            */
  24.  
  25. #ifndef __ERRORS__
  26. #include <Errors.h>
  27. #endif
  28.  
  29. #ifndef __MEMORY__
  30. #include <Memory.h>
  31. #endif
  32.  
  33. #ifndef __NOTIFICATION__
  34. #include <Notification.h>
  35. #endif
  36.  
  37. #ifndef __OSUTILS__
  38. #include <OSUtils.h>
  39. #endif
  40.  
  41. #ifndef __RESOURCES__
  42. #include <Resources.h>
  43. #endif
  44.  
  45. #ifndef __SOUND__
  46. #include <Sound.h>
  47. #endif
  48.  
  49. #ifndef __STRING__
  50. #include <String.h>
  51. #endif
  52.  
  53. #ifndef __SYSEQU__
  54. #include <SysEqu.h>
  55. #endif
  56.  
  57. #ifndef __TOOLUTILS__
  58. #include <ToolUtils.h>
  59. #endif
  60.  
  61. #ifndef __TEXTEDITCONTROL__
  62. #include <TextEditControl.h>
  63. #endif
  64.  
  65. #ifndef __UTILITIES__
  66. #include <Utilities.h>
  67. #endif
  68.  
  69.  
  70.  
  71. /*****************************************************************************/
  72.  
  73.  
  74.  
  75. #define PRIORITY        kAENormalPriority
  76. #define kTimeOutInTicks (60 * 30)    /* 30 second timeout. */
  77.  
  78.  
  79.  
  80. /*****************************************************************************/
  81.  
  82.  
  83.  
  84. extern Boolean        gHasAppleEvents;
  85. extern Boolean        gHasPPCToolbox;
  86.  
  87. extern RgnHandle    gCurrentCursorRgn;
  88. extern Cursor        *gCurrentCursor;
  89.  
  90. static pascal OSErr        DoAEAnswer(AppleEvent message, AppleEvent reply, long refcon);
  91. static pascal OSErr        ReceiveConnect(AppleEvent message, AppleEvent reply, long refcon);
  92. static pascal OSErr        ReceiveConnectReply(AppleEvent message, AppleEvent reply);
  93. static pascal OSErr        ReceiveMessage(AppleEvent message, AppleEvent reply, long refcon);
  94. static pascal Boolean    MyIdleProc(EventRecord *event, long *sleep, RgnHandle *mouseRgn);
  95. static pascal Boolean    AEPortFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo);
  96.  
  97.  
  98.  
  99. /*****************************************************************************/
  100.  
  101.  
  102.  
  103. struct triplets{
  104.     AEEventClass    theEventClass;
  105.     AEEventID        theEventID;
  106.     ProcPtr            theHandler;
  107. };
  108. typedef struct triplets triplets;
  109. static triplets keywordsToInstall[] = {
  110.     { kCoreEventClass,        kAEAnswer,            DoAEAnswer },
  111.     { kCustomEventClass,    keyAppConnect,        ReceiveConnect },
  112.     { kCustomEventClass,    keyAppMessage,        ReceiveMessage }
  113. };        /* These are the custom AppleEvents. */
  114.  
  115.  
  116.  
  117. /*****************************************************************************/
  118. /*****************************************************************************/
  119.  
  120.  
  121.  
  122. /* InitCustomAppleEvents
  123. **
  124. ** Install our custom AppleEvents.  This is done in addition to installing
  125. ** the required AppleEvents.  InitAppleEvents, which installs the required
  126. ** AppleEvents, must be called first, since it sets up some global values.
  127. */
  128.  
  129. #pragma segment AppleEvents
  130. void    InitCustomAppleEvents(void)
  131. {
  132.     OSErr    err;
  133.     short    i;
  134.  
  135.     if (gHasAppleEvents) {
  136.         for (i = 0; i < (sizeof(keywordsToInstall) / sizeof(triplets)); ++i) {
  137.             err = AEInstallEventHandler(
  138.                 keywordsToInstall[i].theEventClass,    /* What class to install.  */
  139.                 keywordsToInstall[i].theEventID,    /* Keywords to install.    */
  140.                 keywordsToInstall[i].theHandler,    /* The AppleEvent handler. */
  141.                 0L,                                    /* Unused refcon.           */
  142.                 false                                /* Only for our app.       */
  143.             );
  144.  
  145.             if (err) {
  146.                 Alert(rErrorAlert, nil);
  147.                 return;
  148.             }
  149.         }
  150.     }
  151. }
  152.  
  153.  
  154.  
  155. /*****************************************************************************/
  156.  
  157.  
  158.  
  159. #pragma segment AppleEvents
  160. pascal OSErr    DoAEAnswer(AppleEvent message, AppleEvent reply, long refcon)
  161. {
  162. #pragma unused (refcon)
  163.  
  164.     OSErr    err;
  165.  
  166.     gCurrentCursor = nil;
  167.         /* Force re-calc of cursor region and cursor to use. */
  168.  
  169.     err = ReceiveConnectReply(message, reply);
  170.  
  171.     AEPutParamPtr(                /* RETURN REPLY ERROR, EVEN IF NONE... */
  172.         &reply,                    /* The AppleEvent.              */
  173.         keyReplyErr,            /* AEKeyword                 */
  174.         typeShortInteger,        /* Desired type.             */
  175.         (Ptr)&err,                /* Pointer to area for data. */ 
  176.         sizeof(short)            /* Size of data area.         */
  177.     );
  178.  
  179.     return(noErr);
  180. }
  181.  
  182.  
  183.  
  184. /*****************************************************************************/
  185.  
  186.  
  187.  
  188. /* SendConnect
  189. **
  190. */
  191.  
  192. #pragma segment AppleEvents
  193. OSErr    SendConnect(FileRecHndl frHndl)
  194. {
  195.     AEAddressDesc    remoteUserLoc;
  196.     OSErr            err;
  197.     long            windID[2], size;
  198.     char            hstate;
  199.     Ptr                ptr1, ptr2;
  200.     AppleEvent        theAevt, reply;
  201.     Str255            macText, appText, userName;
  202.     Handle            userNameHndl;
  203.     FSSpec            myFSS;
  204.     short            i;
  205.  
  206.     theAevt.dataHandle = reply.dataHandle = nil;
  207.         /* Make sure disposing of the descriptors is okay in all cases.
  208.         ** This will not be necessary after 7.0b3, since the calls that
  209.         ** attempt to create the descriptors will nil automatically
  210.         ** upon failure. */
  211.  
  212.     err = noErr;
  213.         /* We may not make the first operation that can cause an error,
  214.         ** so we have to initialize err. */
  215.  
  216.     remoteUserLoc.dataHandle = nil;
  217.         /* Make it safe to dispose of in all cases. */
  218.  
  219.     GetIndString(macText, rPPCText, sTitleText);
  220.     GetIndString(appText, rPPCText, sAppText);
  221.     err = MakeTarget(&remoteUserLoc, false, kAEWaitReply,
  222.         macText, appText, AEPortFilter);
  223.             /* Generate the target for the remote user. */
  224.     (*frHndl)->doc.windowID[0]   = windID[0] = TickCount();
  225.     (*frHndl)->doc.windowID[1]   = windID[0];
  226.     (*frHndl)->doc.remoteUserLoc = remoteUserLoc;
  227.  
  228.     if (!err) {        /* Create the AppleEvent... */
  229.         err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  230.             kCustomEventClass,            /* Event class.                 */
  231.             typeAppConnect,                /* Event ID.                 */
  232.             &remoteUserLoc,                /* Address of receiving app. */
  233.             kAutoGenerateReturnID,        /* This value causes the     */
  234.                                         /* AppleEvent manager to     */
  235.                                         /* assign a return ID that     */
  236.                                         /* is unique to the session. */
  237.             kAnyTransactionID,            /* Ignore transaction ID.     */
  238.             &theAevt                    /* Location of event.         */
  239.         );
  240.     }
  241.  
  242.     if (!err) {        /* If we have an empty list to add to... */
  243.         hstate = LockHandleHigh((Handle)frHndl);
  244.         ptr1   = (Ptr)&((*frHndl)->doc);
  245.         ptr2   = (Ptr)&((*frHndl)->doc.endSendInfo);
  246.         size   = (long)ptr2 - (long)ptr1;
  247.         err = AEPutParamPtr(    /* ADD FILE INFO TO THE APPLEEVENT. */
  248.             &theAevt,            /* AppleEvent to add to.           */
  249.             keyAppConnect,        /* AEKeyword.                       */
  250.             typeAppConnect,        /* Desired type.                   */
  251.             ptr1,                /* Pointer to the data to be sent. */
  252.             size                /* Size of the data to be sent.       */
  253.         );
  254.         HSetState((Handle)frHndl, hstate);
  255.     }
  256.  
  257.     if (!err) {
  258.         myFSS = (*frHndl)->fileState.fss;
  259.         err = AEPutParamPtr(    /* ADD WINDOW NAME TO APPLEEVENT. */
  260.             &theAevt,            /* AppleEvent to add to. */
  261.             keyFSS,                /* AEKeyword.             */
  262.             typeFSS,            /* Desired type.         */
  263.             (Ptr)&myFSS,        /* Pointer to the data.     */
  264.             sizeof(FSSpec)        /* Size of the data.     */
  265.         );
  266.     }
  267.  
  268.     if (!err) {
  269.         userName[0] = 0;
  270.         if (userNameHndl = GetResource('STR ', -16096))
  271.             pstrcpy(userName, (char *)(*userNameHndl));
  272.         err = AEPutParamPtr(    /* ADD USER NAME TO APPLEEVENT. */
  273.             &theAevt,            /* AppleEvent to add to. */
  274.             keyPascal,            /* AEKeyword.             */
  275.             typePascal,            /* Desired type.         */
  276.             userName,            /* Pointer to the data.     */
  277.             userName[0] + 1        /* Size of the data.     */
  278.         );
  279.     }
  280.  
  281.     if (!err) {        /* If we have an AppleEvent ready to send... */
  282.         err = AESend(        /* SEND APPLEEVENT.                */
  283.             &theAevt,        /* Our Apple Event to send.        */
  284.             &reply,            /* We may have a reply.            */
  285.             kAEQueueReply,    /* Type of reply.                */
  286.             PRIORITY,        /* App. send priority.            */
  287.             0,                /* We aren't waiting.            */
  288.             nil,            /* We aren't waiting.            */
  289.             nil                /* EventFilterProcPtr.            */
  290.         );
  291.     }
  292.     if (remoteUserLoc.descriptorType == typeProcessSerialNumber)
  293.         err = ReceiveConnectReply(reply, reply);
  294.             /* If we want q queue reply, and if we are sending to ourselves,
  295.             ** then we already have the reply.  Since we are sending to
  296.             ** ourselves, we don't have to wait for an event.  Stuff happens
  297.             ** right away.  We're (probably) happy. */
  298.  
  299.     AEDisposeDesc(&theAevt);
  300.     AEDisposeDesc(&reply);
  301.         /* Dispose of the descriptors, created or not.
  302.         ** If not created, no harm done by calling. */
  303.  
  304.     if (err) {
  305.         AEDisposeDesc(&remoteUserLoc);
  306.             /* If we didn't connect, get rid of the target descriptor. */
  307.  
  308.         for (i = 0; i < 2; ++i) (*frHndl)->doc.windowID[i] = 0;
  309.             /* Mark this window so that it will never be found if we somehow
  310.             ** do get an answer from the receiver, even after failure. */
  311.     }
  312.  
  313.     return(err);
  314. }
  315.  
  316.  
  317.  
  318. /*****************************************************************************/
  319.  
  320.  
  321.  
  322. /* ReceiveConnect
  323. **
  324. */
  325.  
  326. #pragma segment AppleEvents
  327. pascal OSErr    ReceiveConnect(AppleEvent message, AppleEvent reply, long refcon)
  328. {
  329. #pragma unused (refcon)
  330.  
  331.     OSErr            err;
  332.     FileRecHndl        frHndl;
  333.     char            hstate;
  334.     Ptr                ptr1, ptr2;
  335.     long            size, windID[2];
  336.     AEAddressDesc    senderTarget;
  337.     DescType        ignoredType;
  338.     Size            ignoredSize;
  339.     FSSpec            myFSS;
  340.     Str255            userName;
  341.     Handle            userNameHndl;
  342.  
  343.     err = noErr;
  344.     AEPutParamPtr(                /* RETURN REPLY ERROR, EVEN IF NONE... */
  345.         &reply,                    /* The AppleEvent.              */
  346.         keyReplyErr,            /* AEKeyword                 */
  347.         typeShortInteger,        /* Desired type.             */
  348.         (Ptr)&err,                /* Pointer to area for data. */ 
  349.         sizeof(short)            /* Size of data area.         */
  350.     );
  351.  
  352.     IncNewFileNum(false);
  353.     err = AppNewDocument(&frHndl);
  354.     IncNewFileNum(true);
  355.  
  356.     if (err) return(err);
  357.  
  358.     if (!err) {
  359.         hstate = LockHandleHigh((Handle)frHndl);
  360.         ptr1   = (Ptr)&((*frHndl)->doc);
  361.         ptr2   = (Ptr)&((*frHndl)->doc.endSendInfo);
  362.         size   = (long)ptr2 - (long)ptr1;
  363.         err = AEGetParamPtr(    /* GET CONNECT INFO FROM THE APPLEEVENT. */
  364.             &message,            /* The AppleEvent.              */
  365.             keyAppConnect,        /* AEKeyword                 */
  366.             typeAppConnect,        /* Desired type.             */
  367.             &ignoredType,        /* Type code.                 */
  368.             ptr1,                /* Pointer to area for data. */ 
  369.             size,                /* Size of data area.         */
  370.             &ignoredSize        /* Returned size of data.     */
  371.         );
  372.         HSetState((Handle)frHndl, hstate);
  373.     }
  374.  
  375.     if (!err) {
  376.         err = AEGetAttributeDesc(    /* GET ADDRESS OF SENDER.     */
  377.             &message,                /* Get address of sender from message.         */
  378.             keyAddressAttr,            /* We want an address.                         */
  379.             typeWildCard,            /* We want the address of the sender.         */
  380.             &senderTarget            /* Address of sender.                         */
  381.         );
  382.         if (!err) {
  383.             (*frHndl)->doc.remoteUserLoc = senderTarget;
  384.             err = AEGetParamPtr(    /* GET FSSpec (FOR WINDOW NAME) FROM APPLEEVENT. */
  385.                 &message,            /* The AppleEvent.              */
  386.                 keyFSS,                /* AEKeyword                 */
  387.                 typeFSS,            /* Desired type.             */
  388.                 &ignoredType,        /* Type code.                 */
  389.                 (Ptr)&myFSS,        /* Pointer to area for data. */ 
  390.                 sizeof(FSSpec),        /* Size of the data.         */
  391.                 &ignoredSize        /* Returned size of data.     */
  392.             );
  393.             if (!err)
  394.                 pstrcpy((*frHndl)->fileState.fss.name, myFSS.name);
  395.         }
  396.         if (!err) {
  397.             err = AEGetParamPtr(    /* GET USER NAME FROM APPLEEVENT. */
  398.                 &message,            /* The AppleEvent.              */
  399.                 keyPascal,            /* AEKeyword                 */
  400.                 typePascal,            /* Desired type.             */
  401.                 &ignoredType,        /* Type code.                 */
  402.                 userName,            /* Pointer to area for data. */ 
  403.                 sizeof(Str255),        /* Size of the data.         */
  404.                 &ignoredSize        /* Returned size of data.     */
  405.             );
  406.             (*frHndl)->doc.remoteUserName[0] = 0;
  407.             if (!err)
  408.                 pstrcpy((*frHndl)->doc.remoteUserName, userName);
  409.         }
  410.     }
  411.  
  412.     if (!err) {        /* If we got the remote user address... */
  413.  
  414.         (*frHndl)->doc.windowID[0] = windID[0] = TickCount();
  415.         (*frHndl)->doc.connected = true;
  416.  
  417.         if ((*frHndl)->doc.version != kVersion) err = errAEWrongDataType;
  418.             /* Incompatible file format. */
  419.  
  420.         if (!err) {
  421.             windID[1] = (*frHndl)->doc.windowID[1];
  422.             err = AEPutParamPtr(    /* RETURN RECEIVER WINDOW ID. */
  423.                 &reply,                /* The AppleEvent.              */
  424.                 keyWindowID,        /* AEKeyword                 */
  425.                 typeDoubleLong,        /* Type code.                 */
  426.                 (Ptr)&windID[0],    /* Pointer to area for data. */ 
  427.                 2 * sizeof(long)    /* Size of data area.         */
  428.             );
  429.         }
  430.  
  431.         if (!err) {
  432.             userName[0] = 0;
  433.             if (userNameHndl = GetResource('STR ', -16096))
  434.                 pstrcpy(userName, (char *)(*userNameHndl));
  435.             err = AEPutParamPtr(    /* RETURN RECEIVER USER NAME. */
  436.                 &reply,                /* The AppleEvent.              */
  437.                 keyPascal,            /* AEKeyword                 */
  438.                 typePascal,            /* Type code.                 */
  439.                 userName,            /* Pointer to area for data. */ 
  440.                 userName[0] + 1        /* Size of data area.         */
  441.             );
  442.         }
  443.  
  444.         if (!err) err = AppNewWindow(frHndl, nil);
  445.             /* If connecting worked, create a window for the document. */
  446.     }
  447.  
  448.     if (err) AppDisposeDocument(frHndl);
  449.  
  450.     if (!err) NotifyUser();
  451.     return(err);
  452. }
  453.  
  454.  
  455.  
  456. /*****************************************************************************/
  457.  
  458.  
  459.  
  460. #pragma segment AppleEvents
  461. pascal OSErr    ReceiveConnectReply(AppleEvent message, AppleEvent reply)
  462. {
  463. #pragma unused (reply)
  464.  
  465.     OSErr            err, replyErr;
  466.     DescType        actualType;
  467.     long            windID[2], actualSize;
  468.     WindowPtr        window;
  469.     FileRecHndl        frHndl;
  470.     Str255            userName;
  471.  
  472.     err = AEGetParamPtr(        /* CHECK FOR A RECEIVER ERROR... */
  473.         &message,                /* The AppleEvent.              */
  474.         keyReplyErr,            /* AEKeyword                 */
  475.         typeShortInteger,        /* Desired type.             */
  476.         &actualType,            /* Type code.                 */
  477.         (Ptr)&replyErr,            /* Pointer to area for data. */ 
  478.         sizeof(short),            /* Size of data area.         */
  479.         &actualSize                /* Returned size of data.     */
  480.     );
  481.     if (!err) err = replyErr;
  482.  
  483.     if (!err) {
  484.         err = AEGetParamPtr(    /* GET RECEIVER WINDOW ID. */
  485.             &message,            /* The AppleEvent.              */
  486.             keyWindowID,        /* AEKeyword                 */
  487.             typeDoubleLong,        /* Desired type.             */
  488.             &actualType,        /* Type code.                 */
  489.             (Ptr)&windID[0],    /* Pointer to area for data. */ 
  490.             2 * sizeof(long),    /* Size of data area.         */
  491.             &actualSize            /* Returned size of data.     */
  492.         );
  493.     }
  494.  
  495.     if (!err) {        /* If we got the receiver window ID... */
  496.  
  497.         window = GetAEWindow(windID[1], windID[1]);
  498.             /* The ID's are still both ours, since this is where we
  499.             ** get the receiver's ID returned.  windID[0] holds the
  500.             ** receiver's ID, and windID[1] holds ours. */
  501.  
  502.         if (window) {
  503.             frHndl = (FileRecHndl)GetWRefCon(window);
  504.             if (!(*frHndl)->doc.connected) {
  505.                 err = AEGetParamPtr(
  506.                     &message,            /* The AppleEvent.              */
  507.                     keyPascal,            /* AEKeyword                 */
  508.                     typePascal,            /* Desired type.             */
  509.                     &actualType,        /* Type code.                 */
  510.                     userName,            /* Pointer to area for data. */ 
  511.                     sizeof(Str255),        /* Size of data area.         */
  512.                     &actualSize            /* Returned size of data.     */
  513.                 );
  514.  
  515.                 (*frHndl)->doc.remoteUserName[0] = 0;
  516.                 if (!err) {
  517.                     (*frHndl)->doc.windowID[1] = windID[0];
  518.                     pstrcpy(&(*frHndl)->doc.remoteUserName[0], userName);
  519.                     (*frHndl)->doc.connected = true;
  520.                 }
  521.                 else
  522.                     (*frHndl)->doc.windowID[0] = (*frHndl)->doc.windowID[1] = 0;
  523.             }
  524.         }
  525.     }
  526.  
  527.     return(err);
  528. }
  529.  
  530.  
  531.  
  532. /*****************************************************************************/
  533.  
  534.  
  535.  
  536. /* SendMessage
  537. **
  538. */
  539.  
  540. #pragma segment AppleEvents
  541. OSErr    SendMessage(FileRecHndl frHndl, short messageType)
  542. {
  543.     AEAddressDesc    remoteUserLoc;
  544.     OSErr            err;
  545.     TEHandle        te;
  546.     char            hstate;
  547.     AppleEvent        theAevt, reply;
  548.     Handle            hText;
  549.     long            size, windID[2];
  550.     short            i;
  551.     WindowPtr        oldPort;
  552.  
  553.     if (!(*frHndl)->doc.connected) return(noErr);
  554.  
  555.     oldPort = SetFilePort(frHndl);
  556.  
  557.     theAevt.dataHandle = reply.dataHandle = nil;
  558.         /* Make sure disposing of the descriptors is okay in all cases.
  559.         ** This will not be necessary after 7.0b3, since the calls that
  560.         ** attempt to create the descriptors will nil automatically
  561.         ** upon failure. */
  562.  
  563.     remoteUserLoc = (*frHndl)->doc.remoteUserLoc;
  564.  
  565.     err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  566.         kCustomEventClass,            /* Event class.                 */
  567.         typeAppMessage,                /* Event ID.                 */
  568.         &remoteUserLoc,                /* Address of receiving app. */
  569.         kAutoGenerateReturnID,        /* This value causes the     */
  570.                                     /* AppleEvent manager to     */
  571.                                     /* assign a return ID that     */
  572.                                     /* is unique to the session. */
  573.         kAnyTransactionID,            /* Ignore transaction ID.     */
  574.         &theAevt                    /* Location of event.         */
  575.     );
  576.  
  577.     if (!err) {            /* Say what the message is. */
  578.         AEPutParamPtr(
  579.             &theAevt,
  580.             keyDirectObject,
  581.             typeShortInteger,
  582.             (Ptr)&messageType,
  583.             sizeof(short)
  584.         );
  585.     }
  586.  
  587.     if (!err) {            /* Say what window message is for. */
  588.         for (i = 0; i < 2; ++i) windID[i] = (*frHndl)->doc.windowID[i];
  589.         AEPutParamPtr(
  590.             &theAevt,
  591.             keyWindowID,
  592.             typeDoubleLong,
  593.             (Ptr)&windID[0],
  594.             2 * sizeof(long)
  595.         );
  596.     }
  597.  
  598.     /* The stuff that applies to all messages is now done.  Now specifically
  599.     ** handle all the different message types. */
  600.  
  601.     if (!err) {
  602.         switch (messageType) {
  603.  
  604.             case kDisconnectMssg:
  605.                     /* All the information we need is already in the AppleEvent. */
  606.                 break;
  607.  
  608.             case kTextMssg:
  609.                 te     = (*frHndl)->doc.outBox;
  610.                 hText  = (*te)->hText;
  611.                 hstate = LockHandleHigh(hText);
  612.                 size   = (*te)->teLength;
  613.                 err = AEPutParamPtr(
  614.                     &theAevt,
  615.                     keyAppMessage,
  616.                     typeTextMessage,
  617.                     *hText,
  618.                     size
  619.                 );
  620.                 HSetState(hText, hstate);
  621.                 break;
  622.         }
  623.     }
  624.  
  625.     if (!err) {        /* If everything looks good... */
  626.         err = AESend(                /* SEND APPLEEVENT.                */
  627.             &theAevt,                /* Our Apple Event to send.        */
  628.             &reply,                    /* We may have a reply.            */
  629.             kAENoReply,                /* Don't wait for reply.        */
  630.             PRIORITY,                /* App. send priority.            */
  631.             0,                        /* We aren't waiting.            */
  632.             (IdleProcPtr)MyIdleProc, /* Our only shot at doing some    */
  633.                                      /* work if we are waiting.        */
  634.             nil                        /* EventFilterProcPtr.            */
  635.         );
  636.     }
  637.  
  638.     if (!err) {
  639.         if (messageType == kTextMssg)
  640.             CTESetSelect(0, (*te)->teLength, te);
  641.                 /* Select all the text so entering the next message
  642.                     ** is more convenient. */
  643.     }
  644.  
  645.     AEDisposeDesc(&theAevt);
  646.     AEDisposeDesc(&reply);
  647.         /* Dispose of the descriptors, created or not.
  648.         ** If not created, no harm done by calling. */
  649.  
  650.     SetPort(oldPort);
  651.     return(err);
  652. }
  653.  
  654.  
  655.  
  656. /*****************************************************************************/
  657.  
  658.  
  659.  
  660. #pragma segment AppleEvents
  661. pascal OSErr    ReceiveMessage(AppleEvent message, AppleEvent reply, long refcon)
  662. {
  663. #pragma unused (refcon)
  664.  
  665.     OSErr            err;
  666.     short            messageType;
  667.     WindowPtr        window;
  668.     FileRecHndl        frHndl;
  669.     DescType        actualType;
  670.     long            actualSize, mssgSize, windID[2];
  671.     char            hstate;
  672.     Handle            mssgData;
  673.     AEAddressDesc    remoteUserLoc;
  674.  
  675.     err = noErr;
  676.     AEPutParamPtr(                /* RETURN REPLY ERROR, EVEN IF NONE... */
  677.         &reply,                    /* The AppleEvent.              */
  678.         keyReplyErr,            /* AEKeyword                 */
  679.         typeShortInteger,        /* Desired type.             */
  680.         (Ptr)&err,                /* Pointer to area for data. */ 
  681.         sizeof(short)            /* Size of data area.         */
  682.     );
  683.  
  684.     err = AEGetParamPtr(        /* GET THE MESSAGE TYPE.     */
  685.         &message,                /* The AppleEvent.              */
  686.         keyDirectObject,        /* AEKeyword                 */
  687.         typeShortInteger,        /* Desired type.             */
  688.         &actualType,            /* Type code.                 */
  689.         (Ptr)&messageType,        /* Pointer to area for data. */ 
  690.         2 * sizeof(long),        /* Size of data area.         */
  691.         &actualSize                /* Returned size of data.     */
  692.     );
  693.  
  694.     if (!err) {
  695.         err = AEGetParamPtr(        /* GET WINDOW MESSAGE IS FOR. */
  696.             &message,                /* The AppleEvent.               */
  697.             keyWindowID,            /* AEKeyword                  */
  698.             typeDoubleLong,            /* Desired type.              */
  699.             &actualType,            /* Type code.                  */
  700.             (Ptr)&windID[0],        /* Pointer to area for data.  */ 
  701.             2 * sizeof(long),        /* Size of data area.          */
  702.             &actualSize                /* Returned size of data.      */
  703.         );
  704.     }
  705.  
  706.     if (!err) {            /* See if the requested window exists... */
  707.         if (window = GetAEWindow(windID[1], windID[0])) {
  708.             frHndl = (FileRecHndl)GetWRefCon(window);
  709.                 /* The window still exists... */
  710.         }
  711.         else
  712.             err = userCanceledErr;
  713.                 /* User (or computer) canceled connection by disconnecting improperly. */
  714.     }
  715.  
  716.     if (!err) {        /* If everything is cool, then do the specific task... */
  717.  
  718.         switch(messageType) {
  719.  
  720.             case kDisconnectMssg:
  721.                 remoteUserLoc = (*frHndl)->doc.remoteUserLoc;
  722.                 AEDisposeDesc(&remoteUserLoc);
  723.                 (*frHndl)->doc.connected = false;
  724.                 AdjustMenus();
  725.                 break;
  726.  
  727.             case kTextMssg:
  728.                 if (!err) {        /* Determine the size of the data... */
  729.                     err = AEGetParamPtr(
  730.                         &message,                /* The AppleEvent.              */
  731.                         keyAppMessage,            /* AEKeyword                 */
  732.                         typeTextMessage,        /* Desired type.             */
  733.                         &actualType,            /* Type code.                 */
  734.                         nil,                    /* Pointer to area for data. */ 
  735.                         0,                        /* Size of data area.         */
  736.                         &mssgSize                /* Returned size of data.     */
  737.                     );
  738.                 }
  739.                 mssgData = nil;
  740.                 if (!err) {        /* Get the data... */
  741.                     mssgData = NewHandle(mssgSize);
  742.                     if (mssgData) {
  743.                         hstate = LockHandleHigh(mssgData);
  744.                         err = AEGetParamPtr(
  745.                             &message,                /* The AppleEvent.              */
  746.                             keyAppMessage,            /* AEKeyword                 */
  747.                             typeTextMessage,        /* Desired type.             */
  748.                             &actualType,            /* Type code.                 */
  749.                             *mssgData,                /* Pointer to area for data. */ 
  750.                             mssgSize,                /* Size of data area.         */
  751.                             &actualSize                /* Returned size of data.     */
  752.                         );
  753.                     }
  754.                     else err = memFullErr;
  755.                 }
  756.                 if (!err) mssgData = CTESwapText((*frHndl)->doc.inBox, mssgData, true);
  757.                 if (mssgData) DisposHandle(mssgData);
  758.                 if (!err) NotifyUser();
  759.                 break;
  760.  
  761.         }
  762.     }
  763.  
  764.     return(err);
  765. }
  766.  
  767.  
  768.  
  769. /*****************************************************************************/
  770. /*****************************************************************************/
  771.  
  772.  
  773.  
  774. /* GetAEWindow
  775. **
  776. ** Find the window with the specified window ID's.
  777. */
  778.  
  779. #pragma segment AppleEvents
  780. WindowPtr    GetAEWindow(long windID_0, long windID_1)
  781. {
  782.     WindowPeek    window;
  783.     FileRecHndl    frHndl;
  784.  
  785.     for (window = *(WindowPeek *)WindowList; window; window = window->nextWindow) {
  786.         if (IsAppWindow((WindowPtr)window)) {
  787.             frHndl = (FileRecHndl)GetWRefCon((WindowPtr)window);
  788.             if (
  789.                 ((*frHndl)->doc.windowID[0] == windID_0) &&
  790.                 ((*frHndl)->doc.windowID[1] == windID_1)
  791.             ) return((WindowPtr)window);
  792.         }
  793.     }
  794.  
  795.     return(nil);
  796. }
  797.  
  798.  
  799.  
  800. /*****************************************************************************/
  801.  
  802.  
  803.  
  804. /* MyIdleProc
  805. **
  806. ** This routine gets either an updateEvt, an activateEvt, a nullEvent or an
  807. ** OSEvent.  The first time called it will get a nullEvent; this is its chance
  808. ** to set the sleep value and mouseRegion that will be passed to WaitNextEvent
  809. ** by the caller within the AEM.  After that it will also get events of the
  810. ** other types (which are lost if masked out by the AEM) and must do with them
  811. ** whatever is appropriate.
  812. */
  813.  
  814. #pragma segment AppleEvents
  815. pascal Boolean    MyIdleProc(EventRecord *event, long *sleep, RgnHandle *mouseRgn)
  816. {
  817.     switch (event->what) {
  818.  
  819.         case updateEvt:
  820.         case activateEvt:
  821.         case kOSEvent:
  822.  
  823.             /* These events are passed by the AppleEvent manager to avoid
  824.                dropping while waiting for a reply or notification.  Every
  825.                procedure should handle these events in their idle procedure.
  826.                In this code, we simply dispatch these events back to the
  827.                main event loop handling code. */
  828.  
  829.             DoCursor(false, 0);
  830.             DoEvent(event);
  831.             break;
  832.  
  833.  
  834.         case nullEvent:
  835.  
  836.             /* The idle procedure is called once with the null event before
  837.                the loop begins.  This allows the application to alter sleep
  838.                time and mouseRgn to meet its own needs.  Since we're doing
  839.                nothing, set the cursor to a watch. */
  840.  
  841.             DoCursor(true, 'wait');
  842.  
  843.             *mouseRgn = gCurrentCursorRgn;
  844.             *sleep = 60;        /* This is just like the WaitNextEvent
  845.                                    sleeptime, so use the correct value for
  846.                                    your application.  It's better to use a
  847.                                    non-zero value here rather than zero,
  848.                                    as using zero really slows you down. */
  849.  
  850.             /* DoIdle(); */        /* Application's idle handling. */
  851.             break;
  852.  
  853.         default:
  854.             Alert(rErrorAlert, nil);
  855.             break;
  856.     }
  857.     return(false);
  858. }
  859.  
  860.  
  861.  
  862. /*****************************************************************************/
  863.  
  864.  
  865.  
  866. /* AEPortFilter
  867. **
  868. ** Don't allow PPCBrowser to show any applications other than CShell.
  869. */
  870.  
  871. #pragma segment AppleEvents
  872. pascal Boolean    AEPortFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo)
  873. {
  874. #pragma unused (locationName)
  875.  
  876.     long    type;
  877.  
  878.     if (thePortInfo->name.portKindSelector == ppcByString) {
  879.         BlockMove(thePortInfo->name.u.portTypeStr + 1, (Ptr)&type, 4);
  880.             /* The BlockMove is so that we don't get an address error
  881.             ** on a 68000-based machine due to referencing a long at
  882.             ** an odd-address. */
  883.         if (type == docCreator) return(true);
  884.     }
  885.  
  886.     return(false);
  887. }
  888.  
  889.  
  890.  
  891.